# -*- utf-8 -*-
# @Time: 2021/7/26 0:03
# @Author: CACode
from enum import Enum

import requests
from ajson import aj
from django.http import Http404
from rest_framework import status
from rest_framework.exceptions import ParseError
from rest_framework.generics import GenericAPIView
from rest_framework.pagination import PageNumberPagination
from rest_framework.response import Response
from rest_framework.viewsets import ViewSetMixin

from suishoubang import settings


class Result:

    @staticmethod
    def success(**kwargs):
        payload = {
            'code': 200,
            'message': 'ok'
        }
        payload.update(kwargs)
        return Response(payload, status=status.HTTP_200_OK)

    @staticmethod
    def error(**kwargs):
        payload = {
            'code': 500,
            'message': 'error'
        }
        payload.update(kwargs)
        return Response(data=payload, status=status.HTTP_200_OK if 'code' not in kwargs.keys() else kwargs['code'])


def is_login(key=None, header_token=False):
    """
    是否已经登录，通过验证请求头HTTP_AUTHORIZATION

    如果已经登录并且setter=True，则设置一个字段名为user_obj的用户实例
    """

    def decorator(func):
        def wrapper(*args, **kwargs):
            req = args[len(args) - 1]
            token = req.META.get('HTTP_AUTHORIZATION')
            from django.core.cache import cache
            user_info = None
            if not token:
                return Result.error(code=status.HTTP_403_FORBIDDEN, message="请先登录")
            if cache.has_key(token):
                user_info = cache.get(token)
            if not user_info:
                return Result.error(code=status.HTTP_403_FORBIDDEN, message="请先登录")

            # 验证用户账号密码
            from apps.baseData.models import User
            user_item = User.objects.filter(id=user_info['id'], password=user_info['password'])
            if not user_item:
                # 如果用户已经过期，立刻删除缓存
                cache.delete_pattern(token)
                return Result.error(code=status.HTTP_403_FORBIDDEN, message="用户账号已过期")
            if key:
                kwargs[key] = user_item.first()

            if header_token:
                kwargs['token'] = token
            return func(*args, **kwargs)

        return wrapper

    return decorator


class MyPageNumber(PageNumberPagination):
    page_size = 10  # 每页显示多少条
    page_size_query_param = 'size'  # URL中每页显示条数的参数
    page_query_param = 'page'  # URL中页码的参数
    max_page_size = None  # 最大页码数限制


class GetObjectMixin:
    """
    从请求体中获取id，用于替换gengericapiview中的get_object方法
    """

    def get_object(self, field="id"):
        obj_id = self.request.data.get(field, None)
        try:
            self.queryset = self.queryset or self.get_queryset()
            return self.queryset.get(id=int(obj_id))
        except self.queryset.model.DoesNotExist:
            raise Http404
        except (ValueError, TypeError):
            raise ParseError("参数不正确,请带上id")


class CustomGenericViewSet(GetObjectMixin, ViewSetMixin, GenericAPIView):
    """将类转换成可以多个方法不同请求的类"""
    pass


class Request:
    @staticmethod
    def get(url, json_format=True, params=None, **kwargs):
        req_obj = requests.get(url, params, **kwargs)
        req_obj.encoding = 'utf8'
        text = req_obj.text
        if json_format:
            return aj.load(text)
        return text

    @staticmethod
    def post(url, data=None, json=None, **kwargs):
        req_obj = requests.post(url, data, json, **kwargs)
        req_obj.encoding = 'utf8'
        return req_obj


class AMapAttrs(Enum):
    # 逆地理的api地址

    REGEO_URL = "https://restapi.amap.com/v3/geocode/regeo?key={}&location={}&poitype={}&radius={}&extensions={}&batch={}&roadlevel={}"


class AMap:
    """高德地图工具类"""

    # 反查接口
    @staticmethod
    def regeo(location, poitype=None, radius=1000, extensions='base', batch='false', roadlevel='1'):
        """坐标反查逆地理

        服务示例：

        https://restapi.amap.com/v3/geocode/regeo?output=xml&location=116.310003,39.991957&key=<用户的key>&radius=1000&extensions=all

        参数	值	备注	必选

        :parma location    116.481488,39.990464    经纬度坐标;最多支持20个坐标点;多个点之间用"|"分割。   是

        :parma poitype        商务写字楼        支持传入POI TYPECODE及名称；支持传入多个POI类型，多值间用“|”分隔	否

        :parma radius        1000        查询POI的半径范围。取值范围：0~3000,单位：米	否

        :parma extensions        all        返回结果控制	否

        :parma batch        false        batch=true为批量查询。batch=false为单点查询	否

        :parma roadlevel        0        可选值：1，当roadlevel=1时，过滤非主干道路，仅输出主干道路数据	否

        """
        url = AMapAttrs.REGEO_URL.value.format(settings.AMAP_WEB_KEY, location, poitype, radius, extensions, batch,
                                               roadlevel)
        json_data = Request.get(url)
        return json_data


if __name__ == '__main__':
    json_data = AMap.regeo('113.275824,22.994826')
    print(json_data)
